package com.wanxi.step07test.config;

import com.wanxi.step07test.dto.RestAuthenticationEntryPoint;
import com.wanxi.step07test.dto.RestfulAccessDeniedHandler;
import com.wanxi.step07test.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

// @Configuration有了以下任何一个注解都可以不用
//@Configuration
// @EnableWebSecurity这个表示启用Web安全的注解，如果你已经是是一个web 项目，不需要使用此注解，
// Springboot的自动配置机制WebSecurityEnablerConfiguration已经引入了该注解
//@EnableWebSecurity
//开启这个来判断用户对某个控制层的方法是否具有访问权限（见ProductController的@PreAuthorize）
// 这个注解很重要，如果没有这个注解，那么Controller里的方法将不受约束，只要登录成功就能访问，而无视是否有改权限。
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfigure extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
    @Autowired
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;



    @Override
    protected void configure(HttpSecurity http) throws Exception {

//                第二步:我们用我们自己的数据库数据来完成权限验证
        // 开启跨域和关闭csrf保护
        http.cors().disable().csrf().disable()
                .authorizeRequests()
                // 对某些特定的url不进行认证
                .antMatchers("/code","/login","/upload").permitAll()

//                swagger的路径放行
                .antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui",
                        "/swagger-resources", "/swagger-resources/configuration/security",
                        "/swagger-ui.html", "/webjars/**").permitAll()
                //对预检放行
                .antMatchers(HttpMethod.OPTIONS).permitAll()

                // 其它请求要认证
                .anyRequest().authenticated()
                // 确保使用无状态会话(stateless session)
                //Spring Security永远不会创建一个HttpSession，也永远不会使用它获取SecurityContext
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                // 这一步，告诉Security 框架，我们要用自己的UserDetailsService实现类
                // 来传递UserDetails对象给框架，框架会把这些信息生成Authorization对象使用
                .and().userDetailsService(userDetailsService);
        // 在UsernamePasswordAuthenticationFilter过滤前,我们使用jwt进行过滤
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        //添加自定义未授权和未登录结果返回
        http.exceptionHandling()
                .accessDeniedHandler(restfulAccessDeniedHandler)
                .authenticationEntryPoint(restAuthenticationEntryPoint);

    }



}
